#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <error.h>
#include <net/route.h>
#include <net/if_arp.h>
#include <string.h>
#include "usys.h"

int isVaildIp(const char* ip)
{
	int     dots = 0;                                   //字符 . 的个数
	int     setions = 0;                                //ip每一部分总和（0-255）
	int     strnum = 0;                                 //字符串长度记录

	if (NULL == ip || *ip == '.')                       //排除输入参数为NULL, 或者第一个字符为'.'的字符串    
	{
		return  0;                                  //格式错误
	}

	while (*ip)                                         //字符串不为空
	{
		if (*ip == '.')                                 //如果当前字符为点.则开始判断上一段是否合法在0~255之间
		{
			dots++;                                     //字符 . 的个加一
			if (setions >= 0 && setions <= 255)         //检查ip是否合法
			{
				setions = 0;                            //对上一段IP总和进行清零
			}
			else
			{  
				return  0;                          //格式错误，某一段数值不在0~255之间
			}
		}
		else if (*ip >= '0' && *ip <= '9')              //判断是不是数字
		{
			setions = setions * 10 + (*ip - '0');       //求每一段总和
		}
		else
		{
			return 0;                              //该字符既不是数字也不是点
		}
		ip++;                                           //指向下一个字符
		if (++strnum>15)                                //3*4+3=15,IP地址字符串非结束符字符数最多15个
		{
			return 0;                              //防止出现“1234567890987654321.”这种前面全是数字的字符串输入进来。
		}
	}
	/*判断IP最后一段是否合法*/
	if (setions >= 0 && setions <= 255)
	{                 
		if (dots == 3)                                  //防止出现：“192.168.123”这种不是三个点的情况
		{
			return  1;                               //IP地址合法正确
		}
	}
	return  0;
}


typedef struct cpu_occupy_          //定义一个cpu occupy的结构体
{
    char name[20];                  //定义一个char类型的数组名name有20个元素
    unsigned int user;              //定义一个无符号的int类型的user
    unsigned int nice;              //定义一个无符号的int类型的nice
    unsigned int system;            //定义一个无符号的int类型的system
    unsigned int idle;              //定义一个无符号的int类型的idle
    unsigned int iowait;
    unsigned int irq;
    unsigned int softirq;
}cpu_occupy_t;
 
double cal_cpuoccupy (cpu_occupy_t *o, cpu_occupy_t *n)
{
    double od, nd;
    double id, sd;
    double cpu_use ;
 
    od = (double) (o->user + o->nice + o->system +o->idle+o->softirq+o->iowait+o->irq);//第一次(用户+优先级+系统+空闲)的时间再赋给od
    nd = (double) (n->user + n->nice + n->system +n->idle+n->softirq+n->iowait+n->irq);//第二次(用户+优先级+系统+空闲)的时间再赋给od
 
    id = (double) (n->idle);    //用户第一次和第二次的时间之差再赋给id
    sd = (double) (o->idle) ;    //系统第一次和第二次的时间之差再赋给sd
    if((nd-od) != 0)
        cpu_use =100.0 - ((id-sd))/(nd-od)*100.00; //((用户+系统)乖100)除(第一次和第二次的时间差)再赋给g_cpu_used
    else 
        cpu_use = 0;
    return cpu_use;
}
 
void get_cpuoccupy (cpu_occupy_t *cpust)
{
    FILE *fd;
    char buff[256];
    cpu_occupy_t *cpu_occupy;
    cpu_occupy=cpust;
 
    fd = fopen ("/proc/stat", "r");
    if(fd == NULL)
    {
            perror("fopen:");
            exit (0);
    }
    fgets (buff, sizeof(buff), fd);
 
    sscanf (buff, "%s %u %u %u %u %u %u %u", cpu_occupy->name, &cpu_occupy->user, &cpu_occupy->nice,&cpu_occupy->system, &cpu_occupy->idle ,&cpu_occupy->iowait,&cpu_occupy->irq,&cpu_occupy->softirq);
 
    fclose(fd);
}
 
double get_sysCpuUsage()
{
    cpu_occupy_t cpu_stat1;
    cpu_occupy_t cpu_stat2;
    double cpu;
    get_cpuoccupy((cpu_occupy_t *)&cpu_stat1);
    sleep(1);
    //第二次获取cpu使用情况
    get_cpuoccupy((cpu_occupy_t *)&cpu_stat2);
 
    //计算cpu使用率
    cpu = cal_cpuoccupy ((cpu_occupy_t *)&cpu_stat1, (cpu_occupy_t *)&cpu_stat2);
 
    return cpu;
}

#define SYS_MEM_NAME_LEN 20
#define SYS_MEM_BUFF_LEN 256
#define SYS_100_PERSENT 100

int get_sysMemUsage()
{
	FILE *fd;

	char buff[SYS_MEM_BUFF_LEN];

	double mem_used_rate;

	char name01[SYS_MEM_NAME_LEN];

	unsigned long mem_total;

	char name02[SYS_MEM_NAME_LEN];

	char name11[SYS_MEM_NAME_LEN];

	unsigned long mem_free;

	char name12[SYS_MEM_NAME_LEN];

	fd = fopen ("/proc/meminfo", "r");

	fgets (buff, sizeof(buff), fd);

	sscanf (buff, "%s %lu %s\n", name01, &mem_total, name02);

	fgets (buff, sizeof(buff), fd);

	sscanf (buff, "%s %lu %s\n", name11, &mem_free, name12);

	mem_used_rate = (1.0 - (double)mem_free/(double)mem_total) * SYS_100_PERSENT;

	fclose(fd);

	return mem_used_rate;

}



int SetIfAddr(char *ifname, char *Ipaddr, char *mask,char *gateway)
{
    int fd;
    struct ifreq ifr; 
    struct sockaddr_in *sin;
 
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd < 0)
    {
            perror("socket   error");     
            return -1;     
    }
    memset(&ifr,0,sizeof(ifr)); 
    strcpy(ifr.ifr_name,ifname); 
    sin = (struct sockaddr_in*)&ifr.ifr_addr;     
    sin->sin_family = AF_INET;     
    //IP地址
    inet_aton(Ipaddr,&(sin->sin_addr));   

    if(ioctl(fd,SIOCSIFADDR,&ifr) < 0)   
    {     
        perror("ioctl   SIOCSIFADDR   error");     
        return -3;     
    }
    //子网掩码
    inet_aton(mask,&(sin->sin_addr));
    if(ioctl(fd, SIOCSIFNETMASK, &ifr) < 0)
    {
        perror("ioctl");
        return -5;
    }
    //网关
    struct rtentry route;
    memset( &route, 0, sizeof( route ) );

    struct sockaddr_in *addr = (struct sockaddr_in *)&route.rt_gateway;
    addr->sin_family = AF_INET;
    addr->sin_addr.s_addr = inet_addr(Ipaddr);

    addr = (struct sockaddr_in*) &route.rt_dst;
    addr->sin_family = AF_INET;
    addr->sin_addr.s_addr = inet_addr(gateway);

    addr = (struct sockaddr_in*) &route.rt_genmask;
    addr->sin_family = AF_INET;
    addr->sin_addr.s_addr = INADDR_ANY;

    route.rt_flags = RTF_UP | RTF_GATEWAY;
    route.rt_metric = 0;

    int rc = ioctl( fd, SIOCADDRT, &route );
	if(rc < 0){
		printf("set gateway:%s error\n", gateway);
	}
    close( fd );
	return 0;
}

int set_mac(char* eth, uint8_t* mac)
{
	struct ifreq ifr;
	int fd = 0;
	int ret = -1;
	if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
		return -1;
	}
	ifr.ifr_addr.sa_family = AF_INET;    
	strncpy(ifr.ifr_name, (const char *)eth, IFNAMSIZ - 1 );
	ret = ioctl(fd, SIOCGIFHWADDR, &ifr);
	if(ret < 0){
		printf("get mac failed\n");
		return ret;
	}
	memcpy((unsigned char *)ifr.ifr_hwaddr.sa_data, mac, 6);
	ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
	if(ret < 0){
		printf("set mac failed\n");
		return ret;
	}
	close(fd);
	return ret;
}

int if_updown(char *ifname, int flag)
{
	int fd, rtn;
	struct ifreq ifr;        
	fd = socket(AF_INET, SOCK_DGRAM, 0 );
	if ( fd < 0 ) {
		perror("socket");
		return -1;
	}

	ifr.ifr_addr.sa_family = AF_INET;
	strncpy(ifr.ifr_name, (const char *)ifname, IFNAMSIZ - 1 );
	if ( (rtn = ioctl(fd, SIOCGIFFLAGS, &ifr) ) == 0 ) {
		if (flag){
			ifr.ifr_flags |= IFF_UP;
		}else{
			ifr.ifr_flags &= ~IFF_UP;
		}
	}

	if ( (rtn = ioctl(fd, SIOCSIFFLAGS, &ifr) ) != 0) {
		perror("SIOCSIFFLAGS");
	}
	close(fd);
	return rtn;
}
